#ifndef __STREAM_FILE_H__
#define __STREAM_FILE_H__

#include <iostream>
#include <fstream>
#include "./includes/register_pack.h"
#include "./includes/file_pointer_pack.h"

class StreamFile{
	public:
		typedef unsigned char openmode;
	protected:
		std::string path;
		openmode mode;
		std::fstream file;
		RegisterFactory* factory;
			
		bool ferror;
		bool feof;
		bool fbof;
		bool fcreated;
		
	public:
		static const unsigned char m_read    = 0x01; /* primer bit on -> read */
		static const unsigned char m_write   = 0x02; /* segundo bit on -> write */
	public:
		StreamFile(const std::string path,unsigned char openmode,const RegisterFactory& factory){
			this->path = path;
			this->factory = factory.duplicate();
			this->ferror = false;
			this->feof = false;
			this->fbof = false;
			this->fcreated = false;
			this->mode = openmode;
		}
		virtual ~StreamFile(){
			delete this->factory;
		}

		/* Lo escribe donde puede */
		virtual FilePointer* write(const Register& data) = 0;
		/* Lo escribe donde se le pide */
		virtual FilePointer* update(const Register& data, FilePointer& pointer) = 0;
		/* Lee la posicion pedida */
		virtual Register* read(const FilePointer& pointer) = 0;
		virtual Register* readNext(FilePointer& pointer,bool back=false) = 0;
		/* Libera la posicion indicada */
		virtual void free(const FilePointer& pointer)=0;		
		
		/* Obtengo un puntero al principio para poder iterar a traves de todo el archivo */
		virtual FilePointer* first()=0;
		/* Obtengo un puntero al final para poder iterar a traves de todo el archivo */
		virtual FilePointer* last()=0;
		
		std::string getPath(){ return path; }		

		operator bool(){ return (!ferror); } /* Comprueba si existio algun error(cualquiera) -> true, sin errores */
		bool created(){ return fcreated; }; /* Informa si al crear la clase se creo el archivo(true) o se abrio(false) */	
		bool bof(){ return fbof; }
		bool eof(){ return feof; }
		virtual void peek(const FilePointer& pointer,bool back=false)=0; /* Me permite activar el EOF por adelantado */
		
		virtual std::ostream& toOstream(std::ostream& out)=0;
	protected:
		std::fstream::openmode p_mode(openmode mode){
			std::fstream::openmode ret;
			if( mode&m_read ) ret = std::fstream::in;
			if( mode&m_write ) ret = ret | std::fstream::out;
			return ret;
		}
};

#endif /* __STREAM_FILE_H__ */
